package user

import (
	"regexp"
	"time"

	"golang.org/x/crypto/bcrypt"
	"gorm.io/gorm"

	"BookStack/pkg/errors"
	"BookStack/pkg/utils"
)

// User 用户实体
type User struct {
	ID        uint      `gorm:"primarykey"`
	Username  string    `gorm:"size:50;not null;unique"`
	Email     string    `gorm:"size:100;not null;unique"`
	Password  string    `gorm:"size:100;not null"`
	Nickname  string    `gorm:"size:50"`
	Avatar    string    `gorm:"size:255"`
	Role      string    `gorm:"size:20;default:user"` // user, admin, superadmin
	Status    int       `gorm:"default:1"`            // 0-禁用, 1-正常
	CreatedAt time.Time `gorm:"not null"`
	UpdatedAt time.Time `gorm:"not null"`
	DeletedAt gorm.DeletedAt
}

// TableName 指定表名
func (User) TableName() string {
	return "users"
}

// NewUser 创建新用户
func NewUser(username, email, password, nickname string) (*User, error) {
	// 验证邮箱
	if err := ValidateEmail(email); err != nil {
		return nil, err
	}

	// 验证用户名
	if err := ValidateUsername(username); err != nil {
		return nil, err
	}

	// 验证密码
	if err := ValidatePassword(password); err != nil {
		return nil, err
	}

	// 加密密码
	hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
	if err != nil {
		return nil, err
	}

	now := time.Now()

	// 创建用户
	return &User{
		Username:  username,
		Email:     email,
		Password:  string(hashedPassword),
		Nickname:  nickname,
		Role:      "user", // 默认角色
		Status:    1,      // 默认状态：启用
		CreatedAt: now,
		UpdatedAt: now,
	}, nil
}

// CheckPassword 检查密码是否正确
func (u *User) CheckPassword(password string) bool {
	err := bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(password))
	return err == nil
}

// ChangePassword 修改密码
func (u *User) ChangePassword(newPassword string) error {
	// 验证密码
	if err := ValidatePassword(newPassword); err != nil {
		return err
	}

	// 加密新密码
	hashedPassword, err := bcrypt.GenerateFromPassword([]byte(newPassword), bcrypt.DefaultCost)
	if err != nil {
		return err
	}

	u.Password = string(hashedPassword)
	u.UpdatedAt = parseTime(utils.Now())
	return nil
}

// UpdateProfile 更新用户资料
func (u *User) UpdateProfile(nickname, avatar string) {
	if nickname != "" {
		u.Nickname = nickname
	}
	if avatar != "" {
		u.Avatar = avatar
	}
	u.UpdatedAt = parseTime(utils.Now())
}

// SetRole 设置角色
func (u *User) SetRole(role string) error {
	// 验证角色
	if role != "user" && role != "admin" && role != "superadmin" {
		return errors.New(errors.ErrCodeValidation, "角色无效")
	}

	u.Role = role
	u.UpdatedAt = parseTime(utils.Now())
	return nil
}

// SetStatus 设置状态
func (u *User) SetStatus(status int) error {
	// 验证状态
	if status != 0 && status != 1 {
		return errors.New(errors.ErrCodeInvalidUserStatus, "")
	}

	u.Status = status
	u.UpdatedAt = parseTime(utils.Now())
	return nil
}

// parseTime 解析时间
func parseTime(timeStr string) time.Time {
	t, _ := utils.ParseTime(timeStr)
	return t
}

// IsAdmin 判断是否为管理员
func (u *User) IsAdmin() bool {
	return u.Role == "admin" || u.Role == "superadmin"
}

// IsSuperAdmin 判断是否为超级管理员
func (u *User) IsSuperAdmin() bool {
	return u.Role == "superadmin"
}

// IsActive 判断是否正常状态
func (u *User) IsActive() bool {
	return u.Status == 1
}

// ValidatePassword 验证密码
func ValidatePassword(password string) error {
	if len(password) < 6 || len(password) > 20 {
		if len(password) < 6 {
			return errors.New(errors.ErrCodePasswordMinLength, "")
		}
		return errors.New(errors.ErrCodePasswordMaxLength, "")
	}
	return nil
}

// ValidateEmail 验证邮箱
func ValidateEmail(email string) error {
	if email == "" {
		return errors.New(errors.ErrCodeEmailRequired, "")
	}

	// 验证邮箱格式
	pattern := `^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`
	matched, err := regexp.MatchString(pattern, email)
	if err != nil {
		return errors.New(errors.ErrCodeSystem, "")
	}
	if !matched {
		return errors.New(errors.ErrCodeEmailFormat, "")
	}

	return nil
}

// ValidateUsername 验证用户名
func ValidateUsername(username string) error {
	if username == "" {
		return errors.New(errors.ErrCodeUsernameRequired, "")
	}

	// 验证用户名长度
	if len(username) < 3 {
		return errors.New(errors.ErrCodeUsernameMinLength, "")
	}
	if len(username) > 20 {
		return errors.New(errors.ErrCodeUsernameMaxLength, "")
	}

	// 验证用户名格式
	pattern := `^[a-zA-Z0-9_]+$`
	matched, err := regexp.MatchString(pattern, username)
	if err != nil {
		return errors.New(errors.ErrCodeSystem, "")
	}
	if !matched {
		return errors.New(errors.ErrCodeValidation, "用户名格式不正确，只能包含字母、数字和下划线")
	}

	return nil
}
